﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Reflection;
using System.Collections;

namespace MYSMRM.Common
{
    public class DataTable2Object
    {
        /// <summary>
        /// Convert an DataRow to an object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="row"></param>
        /// <returns></returns>
        public static T ConvertToObject<T>(DataRow row) where T : new()
        {
            System.Object obj = new T();
            if (row != null)
            {
                DataTable dataTable = row.Table;
                GetObject(dataTable.Columns, row, obj);
            }
            if (obj != null && obj is T)
            {
                return (T)obj;
            }
            else
            {
                return default(T);
            }
        }

        /// <summary>
        /// use property's attribute to match
        /// </summary>
        /// <param name="cols"></param>
        /// <param name="dr"></param>
        /// <param name="obj"></param>
        private static void GetObject(DataColumnCollection cols, DataRow dr, System.Object obj)
        {
            ColumnName attribute;
            Type type = obj.GetType();
            PropertyInfo[] pros = type.GetProperties();
            foreach (PropertyInfo pro in pros)
            {
                try
                {
                    attribute = null;
                    attribute = pro.GetCustomAttributes(typeof(ColumnName), false)[0] as ColumnName;
                    if (attribute != null)
                    {
                        if (cols.Contains(attribute.Msg))
                        {
                            if (pro.PropertyType == typeof(Int32))
                            {
                                pro.SetValue(obj, dr[attribute.Msg] == DBNull.Value ? 0 : Convert.ToInt32(dr[attribute.Msg]), null);
                            }
                            else if (pro.PropertyType == typeof(DateTime))
                            {
                                pro.SetValue(obj, dr[attribute.Msg] == DBNull.Value ? DateTime.Now : Convert.ToDateTime(dr[attribute.Msg]), null);
                            }
                            else if (pro.PropertyType == typeof(Boolean))
                            {
                                pro.SetValue(obj, dr[attribute.Msg] == DBNull.Value ? false : Convert.ToBoolean(dr[attribute.Msg]), null);
                            }
                            else
                            {
                                pro.SetValue(obj, dr[attribute.Msg] == DBNull.Value ? null : dr[attribute.Msg], null);
                            }
                        }
                    }
                }
                catch (Exception e)
                { 
                    //do nothing shine 20130524
                }
            }
        }

        // use property's name to match
        //private static void GetObject(DataColumnCollection cols, DataRow dr, System.Object obj)
        //{
        //    Type type = obj.GetType();
        //    PropertyInfo[] pros = type.GetProperties();
        //    foreach (PropertyInfo pro in pros)
        //    {
        //        if (cols.Contains(pro.Name))
        //        {
        //            pro.SetValue(obj, dr[pro.Name] == DBNull.Value ? null : dr[pro.Name], null);
        //        }
        //    }
        //}

        /// <summary>
        /// Convert a data table to an objct list  
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dataTable"></param>
        /// <returns></returns>
        public static List<T> ConvertToList<T>(DataTable dataTable) where T : new()
        {
            List<T> list = new List<T>();
            foreach (DataRow row in dataTable.Rows)
            {
                T obj = ConvertToObject<T>(row);
                list.Add(obj);
            }
            return list;
        }
        /// <summary>
        /// Convert object collection to an data table  
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        //public static DataTable ConvertToDataTableFromList(System.Object list)
        //{
        //    DataTable dt = null;
        //    System.Type listType = list.GetType();
        //    if (listType.IsGenericType)
        //    {
        //        System.Type type = listType.GetGenericArguments()[0];
        //        dt = new DataTable(type.Name + "List");
        //        MemberInfo[] mems = type.GetMembers(BindingFlags.Public | BindingFlags.Instance);

        //        #region create table construction
        //        foreach (MemberInfo mem in mems)
        //        {
        //            //switch(mem.MemberType)
        //            //{
        //            //    case MemberTypes.Property:
        //            //        {
        //            //            dt.Columns.Add(((PropertyInfo)mem).Name,typeof(System.String));
        //            //            break;
        //            //        }
        //            //    case MemberTypes.Field:
        //            //        {
        //            //            dt.Columns.Add(((FieldInfo)mem).Name,typeof(System.String));
        //            //            break;
        //            //        }
        //            //}
        //            dt.Columns.Add(mem.Name, mem.ReflectedType);
        //        }
        //        #endregion
        //        #region fill values
        //        IList iList = list as IList;
        //        foreach (System.Object record in iList)
        //        {
        //            System.Int32 i = 0;
        //            System.Object[] fieldValues = new System.Object[dt.Columns.Count];
        //            foreach (DataColumn dataColumn in dt.Columns)
        //            {
        //                MemberInfo mem = listType.GetMember(dataColumn.ColumnName)[0];
        //                switch (mem.MemberType)
        //                {
        //                    case MemberTypes.Field:
        //                        {
        //                            fieldValues[i] = ((FieldInfo)mem).GetValue(record);
        //                            break;
        //                        }
        //                    case MemberTypes.Property:
        //                        {
        //                            fieldValues[i] = ((PropertyInfo)mem).GetValue(record, null);
        //                            break;
        //                        }
        //                }
        //                i++;
        //            }
        //            dt.Rows.Add(fieldValues);
        //        }
        //        #endregion
        //    }
        //    return dt;
        //}

        public static DataTable ConvertToDataTableFromList(System.Object list)
        {
            ColumnName attribute;
            DataTable dt = null;
            System.Type listType = list.GetType();
            if (listType.IsGenericType)
            {
                System.Type type = listType.GetGenericArguments()[0];
                dt = new DataTable(type.Name + "List");
                //MemberInfo[] mems = type.GetMembers(BindingFlags.Public | BindingFlags.Instance);
                PropertyInfo[] pros = type.GetProperties();

                #region create table construction
                foreach (PropertyInfo pro in pros)
                {
                    try
                    {
                        attribute = null;
                        attribute = pro.GetCustomAttributes(typeof(ColumnName), false)[0] as ColumnName;
                        if (attribute != null)
                        {
                            dt.Columns.Add(attribute.Msg, pro.PropertyType);
                        }
                    }
                    catch(Exception e)
                    {
                        //do nothing shine 20130524
                    }
                }
                #endregion

                #region fill values
                IList iList = list as IList;
                foreach (System.Object record in iList)
                {
                    DataRow dr = dt.NewRow();
                    foreach (DataColumn dc in dt.Columns)
                    {
                        foreach (PropertyInfo pro in pros)
                        {
                            try
                            {
                                attribute = null;
                                attribute = pro.GetCustomAttributes(typeof(ColumnName), false)[0] as ColumnName;
                                if (dc.ColumnName == attribute.Msg)
                                {
                                    dr[dc.ColumnName] = pro.GetValue(record, null);
                                    break;
                                }
                            }
                            catch (Exception e)
                            {
                                //do nothing shine 20130524
                            }
                        }
                    }
                    dt.Rows.Add(dr);
                }
                #endregion
            }
            return dt;
        }
    }
}
